package com.chinacoal.hr.levelimpl.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinacoal.hr.levelapi.entity.AttendanceInfo;
import com.chinacoal.hr.levelapi.entity.AttendanceSummary;
import com.chinacoal.hr.levelapi.entity.TransPaperDetailList;
import com.chinacoal.hr.levelimpl.dao.AttendanceSummaryDao;
import com.chinacoal.hr.levelimpl.service.AttendanceInfoService;
import com.chinacoal.hr.levelimpl.service.AttendanceSummaryService;
import com.chinacoal.hr.levelimpl.service.TransPaperDetailListService;
import com.chinacoal.hr.levelimpl.utils.DateUtil;
import com.chinacoal.hr.levelimpl.utils.StaticDicts;
import com.eos.system.utility.Assert;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: YunTao.Li
 * @create: 2019-11-26 15:00
 * @description:
 **/
@Service
public class AttendanceSummaryServiceImpl implements AttendanceSummaryService {


    @Autowired
    private TransPaperDetailListService transPaperDetailListService;

    @Autowired
    private AttendanceSummaryDao attendanceSummaryDao;

    @Autowired
    private AttendanceInfoService attendanceInfoService;

    /**
     * 查询考勤信息汇总带分页
     *
     * @param condition :
     * @return : com.baomidou.mybatisplus.core.metadata.IPage<com.chinacoal.hr.levelimpl.entity.AttendanceSummary>
     * @author : YunTao.Li
     * @date : 2019/11/26 2019/11/26
     */
    public IPage<AttendanceSummary> getAttendanceSummaryList(Map<String, Object> condition) {
        return attendanceSummaryDao.getAttendanceInfoList(condition);
    }

    /**
     * 考勤汇总处理，将请假、出差、申诉的审批记录处理成考勤信息
     *
     * @return : java.util.Map<java.lang.String,java.lang.String>
     * @author : YunTao.Li
     * @date : 2020/7/6 2020/7/6
     */
    @Transactional
    public Map<String, String> attendanceTransPaperProcessor(String empCode, String beginDate, String endDate) throws Throwable {

        // step1 : 根据开始日期与结束日期获得所有xip_hr_pa_list表中 已审批 的事务单明细
        List<TransPaperDetailList> transPaperDetailLists = transPaperDetailListService.getPreValidTransPaperDetailList(empCode, beginDate, endDate);


        // step2 : 遍历事务单明细，修改考勤明细信息
        for (TransPaperDetailList paperDetail : transPaperDetailLists) {
            Date attendDate = paperDetail.getPaDate();
            String timeType = paperDetail.getTimeType();
            String paType = paperDetail.getPaType();

            // TODO: 应该一次查出再循环
            /**
             * 查出考勤明细，并按照timetype来修正考勤的状态
             * 如果是上午请假|差旅，则修改上午状态为正常，同时判断下午状态，如果也为正常则修改全天状态为正常
             * 如果是下午请假|差旅，则修改下午状态为正常，同时判断上午状态，如果也为正常则修改全天状态为正常
             * */
            attendanceInfoService.attendanceInfoFixedByProcess(empCode, attendDate, timeType, paType);
        }

        return null;
    }

    /**
     * 增量统计某段时间的考勤信息
     *
     * @param beginDate : yyyy-MM-dd
     * @param endDate   : yyyy-MM-dd
     * @return : java.util.Map<java.lang.String,java.lang.String>
     * @author : YunTao.Li
     * @date : 2020/7/7 2020/7/7
     */
    @Transactional
    public Map<String, String> attendanceSummaryIncrementRolling(String beginDate, String endDate) throws Throwable {
        Map<String, String> result = new HashMap<String, String>();
        result.put("code", "-1");

        //TODO:yrmonth
        String yrmonth = beginDate.substring(0, 7);

        try {
            // step1 : 获得时间范围内的所有考勤明细数据
            List<AttendanceInfo> attendanceInfos = attendanceInfoService.getAttendanceInfoList(beginDate, endDate);

            /**
             * step2 : 整理考勤明细数据，按人划分
             * key:empcode|value：attendanceInfoList
             */
            Map<String, List> attdanceInfoGroupEmpMap = new ConcurrentHashMap();
            List<AttendanceInfo> attendanceGroupInfoList = null;
            for (AttendanceInfo attendanceInfo : attendanceInfos) {
                String empCode = attendanceInfo.getEmpCode();

                if (attdanceInfoGroupEmpMap.containsKey(empCode)) {
                    attendanceGroupInfoList = attdanceInfoGroupEmpMap.get(empCode);
                    attendanceGroupInfoList.add(attendanceInfo);
                    attdanceInfoGroupEmpMap.put(empCode, attendanceGroupInfoList);
                } else {
                    attendanceGroupInfoList = new ArrayList<AttendanceInfo>();
                    attendanceGroupInfoList.add(attendanceInfo);
                    attdanceInfoGroupEmpMap.put(empCode, attendanceGroupInfoList);
                }
            }

            /**
             * step3 : 计算考勤汇总记录
             * */
            List<AttendanceSummary> attendanceSummaryList = this.attendanceSummaryCalc(attdanceInfoGroupEmpMap, yrmonth, beginDate, endDate);
            this.attendanceSummaryDao.insertBatchAttendanceSummaryRecords(attendanceSummaryList);

        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }

        result.put("code", "1");
        return result;
    }

    /**
     * 汇总统计某年月的考勤信息
     *
     * @param yrmonth :
     * @return : java.util.Map<java.lang.String,java.lang.String>
     * @author : YunTao.Li
     * @date : 2020/7/6 2020/7/6
     */
    @Transactional
    public Map<String, String> attendanceSummaryRolling(String yrmonth) throws Throwable {

        Map<String, String> result = new HashMap<String, String>();
        result.put("code", "-1");

        try {

            // step1 : 清除年月的考勤汇总数据（xip_hr_kq）
            this.deleteAttendanceSummary(yrmonth);

            Map<String, String> monthDayMap = DateUtil.getFirstDayInMonth(yrmonth);

            String firstday = monthDayMap.get("firstday");
            String lastday = monthDayMap.get("lastday");

            // step2 : 统计某段时间的考勤信息
            this.attendanceSummaryIncrementRolling(firstday, lastday);

        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }

        result.put("code", "1");
        return result;
    }

    /**
     * 根据年月删除考勤汇总数据
     *
     * @param yrmonth : yyyy-MM
     * @return : java.util.Map<java.lang.String,java.lang.String>
     * @author : YunTao.Li
     * @date : 2020/7/6 2020/7/6
     */
    public Map<String, String> deleteAttendanceSummary(String yrmonth) throws Throwable {
        Map<String, String> result = new HashMap<String, String>();
        result.put("code", "-1");

        try {
            Map<String, Object> condition = new HashMap<String, Object>();
            condition.put("yrmonth", yrmonth);

            this.attendanceSummaryDao.deleteAttendanceSummaryRecordByCondition(condition);
        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }

        result.put("code", "1");
        return result;
    }

    /**
     * 考勤汇总统计
     *
     * @param attdanceInfoGroupEmpMap : 按人划分，key：empcode，value：人员的考勤明细列表
     * @param yrmonth                 : 年月
     * @param beginDate               : 开始日期 yyyy-MM-dd
     * @param endDate                 : 结束日期 yyyy-MM-dd
     * @return : java.util.List<com.chinacoal.hr.levelimpl.entity.AttendanceSummary>
     * @author : YunTao.Li
     * @date : 2020/7/24 2020/7/24
     */
    @Transactional
    public List<AttendanceSummary> attendanceSummaryCalc(Map<String, List> attdanceInfoGroupEmpMap, String yrmonth, String beginDate, String endDate) throws Throwable {
        List<AttendanceSummary> attendanceSummaryList = new ArrayList<>();
        for (Map.Entry<String, List> entry : attdanceInfoGroupEmpMap.entrySet()) {
            /**
             *  初始化变量
             * */
            String empCode = entry.getKey(); // 人员编码
            List<AttendanceInfo> attendanceInfoList = entry.getValue(); // 考勤明细列表
            int attendanceInfoListSize = attendanceInfoList.size(); // 此人共有多少条考勤明细记录
            AttendanceSummary summary = new AttendanceSummary(); // 考勤汇总bean
            summary.setPeriodCode(yrmonth); // 设置考勤汇总年月
            int expectDays = DateUtil.getYrmonthWorkDayCount(yrmonth);// 应到天数
            int actualDays = 0;// 实到天数
            int notSignUp = 0;//忘记签到次数
            int notSignOut = 0;//忘记签退次数
            int leaveDays = 0;// 旷工次数
            int delaySignNum = 0;// 迟到小于30分钟
            int delaySignNumMore = 0;// 迟到大于30分钟次数
            int preSignNum = 0;// 早退小于30分钟次数
            int preSignNumMore = 0; // 早退大于30分钟次数
            int paTypeSick = 0; // 病假天数
            int paTypePersonal = 0; // 事假天数
            int paTypeAnnual = 0; // 年休假天数
            int paTypeMaternity = 0; // 产假天数
            // 申诉次数
            // 出差天数*
            int paTypeTravel = 0; // 因公外出天数
            // 加班天数
            int paTypeMarital = 0; // 婚假天数
            int paTypePatenity = 0; // 哺乳假天数
            int paTypeFuneral = 0; // 丧假天数
            int paTypeFamilycare = 0; // 探亲假天数
            int paTypeSore = 0; // 工伤假天数
            int paTypePaid = 0; // 培训考试假天数
            int paTypePublic = 0; // 公假天数

            /**
             * step4.1 : 根据事务单明细来修改考勤明细
             * */
            this.attendanceTransPaperProcessor(empCode, beginDate, endDate);

            /**
             * step4.2 : 遍历所有的考勤明细记录，统计考勤汇总信息
             * */
            for (int i = 0; i < attendanceInfoListSize; i++) {
                AttendanceInfo attendanceInfo = attendanceInfoList.get(i);
                attendanceInfo.getAttendDate();
                String paType = attendanceInfo.getHolidayType();

                if (i == 0) {
                    BeanUtils.copyProperties(summary, attendanceInfo);
                }

                // 签到异常
                if (StaticDicts.SIGN_STATUS_UNUSUAL.equals(attendanceInfo.getSignUpStatus())) {
                    int n = StaticDicts.SIGN_UP_TIME - attendanceInfo.getSignUp();
                    if (n < -30) { // 如果830 - 打卡时间比如859 < -30 则迟到大于30分钟
                        delaySignNumMore++;
                    } else if (n < 0) { // 如果830 - 打卡时间比如835 < 0 则迟到
                        delaySignNum++;
                    }
                }
                // 签退异常
                if (StaticDicts.SIGN_STATUS_UNUSUAL.equals(attendanceInfo.getSignOutStatus())) {
                    int n = StaticDicts.SIGN_OUT_TIME - attendanceInfo.getSignOut();
                    if (n > 71) { // 如果1700 - 1630 > 70 则早退大于30分钟
                        preSignNumMore++;
                    } else if (n > 0) { // 如果1700 - 1659 > 0则早退
                        preSignNum++;
                    }
                }

                // 签到漏签
                if (StaticDicts.SIGN_STATUS_MISSING.equals(attendanceInfo.getSignUpStatus())) {
                    notSignUp++;
                }

                // 签退漏签
                if (StaticDicts.SIGN_STATUS_MISSING.equals(attendanceInfo.getSignOutStatus())) {
                    notSignOut++;
                }

                // 即签到漏签又签退漏签，同时又考勤状态异常则为旷工
                if (StaticDicts.SIGN_STATUS_MISSING.equals(attendanceInfo.getSignUpStatus()) && StaticDicts.SIGN_STATUS_MISSING.equals(attendanceInfo.getSignOutStatus()) && StaticDicts.CONFIRM_STATUS_UNUSUAL.equals(attendanceInfo.getConfirmStatus())) {
                    leaveDays++;
                }

                /**
                 *  判断paType
                 * */
                if (StaticDicts.HR_PA_TYPE_PERSONAL.equals(paType)) { // 事假
                    paTypePersonal++;
                } else if (StaticDicts.HR_PA_TYPE_SICK.equals(paType)) { // 病假
                    paTypeSick++;
                } else if (StaticDicts.HR_PA_TYPE_ANNUAL.equals(paType)) { // 年假
                    paTypeAnnual++;
                } else if (StaticDicts.HR_PA_TYPE_MATERNITY.equals(paType)) { // 产假
                    paTypeMaternity++;
                } else if (StaticDicts.HR_PA_TYPE_MARITAL.equals(paType)) { // 婚假
                    paTypeMarital++;
                } else if (StaticDicts.HR_PA_TYPE_PATENITY.equals(paType)) { // 哺乳假
                    paTypePatenity++;
                } else if (StaticDicts.HR_PA_TYPE_FUNERAL.equals(paType)) { // 丧假
                    paTypeFuneral++;
                } else if (StaticDicts.HR_PA_TYPE_FAMILYCARE.equals(paType)) { // 探亲假
                    paTypeFamilycare++;
                } else if (StaticDicts.HR_PA_TYPE_SORE.equals(paType)) { // 工伤假
                    paTypeSore++;
                } else if (StaticDicts.HR_PA_TYPE_PAID.equals(paType)) { // 培训考试假
                    paTypePaid++;
                } else if (StaticDicts.HR_PA_TYPE_PUBLIC.equals(paType)) { // 公假
                    paTypePublic++;
                } else if (StaticDicts.HR_PA_TYPE_TRAVEL.equals(paType)) { // 因公外出
                    paTypeTravel++;
                }
            }
            actualDays = expectDays - leaveDays;

            summary.setExpectDays(expectDays);// 应到天数
            summary.setActualDays(actualDays);// 实到天数
            summary.setNotSignUp(notSignUp); //忘记签到次数
            summary.setNotSignOut(notSignOut); //忘记签退次数
            summary.setLeaveDays(leaveDays); // 旷工次数
            summary.setDelaySignNum(delaySignNum); // 迟到小于30分钟
            summary.setDelaySignNumMore(delaySignNumMore); // 迟到大于30分钟次数
            summary.setPreSignNum(preSignNum); // 早退小于30分钟次数
            summary.setPreSignNumMore(preSignNumMore); // 早退大于30分钟次数
            summary.setSickDays(paTypeSick); // 病假
            summary.setPrivateDays(paTypePersonal); // 事假
            summary.setAnnualDays(paTypeAnnual); // 年休假
            summary.setMaternityDays(paTypeMaternity); // 产假天数
            summary.setMarriageDays(paTypeMarital); // 婚假天数
            summary.setLactationDays(paTypePatenity); // 哺乳假天数
            summary.setFuneralDays(paTypeFuneral); // 丧假天数
            summary.setHomeLeaveDays(paTypeFamilycare); // 探亲假天数
            summary.setInjuryDays(paTypeSore); // 工伤假天数
            summary.setTrainingDays(paTypePaid); // 培训考试假
            summary.setPubLeaveDays(paTypePublic); // 公假天数
            summary.setAwayDays(paTypeTravel); // 因公外出天数

            attendanceSummaryList.add(summary);
        }

        return attendanceSummaryList;
    }
}
